﻿#pragma once
namespace LK
{
	//转换为ToString输出
	std::ostream& operator<<(std::ostream&o, Object const&x);
	//转换为ToString输出
	std::wostream& operator<<(std::wostream&o, Object const&x);
	//转换为ToString输出
	std::ostream& operator<<(std::ostream&o, ptr<Object> &x);
	//转换为ToString输出
	std::wostream& operator<<(std::wostream&o, ptr<Object> &x);

	/**@brief 基类*/
	struct Object
	{
		/**
		@brief 用以推断被代理类型*/
		typedef Object IObj;
		/**
		@brief 用以推断代理类型*/
		typedef ptr<Object> PObj;
		//引用计数
		mutable PRefCount UseCount;
		/**@brief 默认构造函数*/
		Object() {}
		/**@brief 复制构造函数*/
		Object(const Object&obj) :UseCount() {}
		/*operator&重载*/
		Object*operator&() { if (UseCount<0)++UseCount; return this; }
		Object const*operator&()const { if (UseCount<0)++UseCount; return this; }
		/**@brief 赋值函数*/
		Object& operator=(const Object&) { return *this; }
		/**@brief 交换两个对象的内容，而不仅仅交换引用*/
		virtual void SwapWith(PObject&);
		/**@brief 判断两者是否相等*/
		virtual bool Equals(PObject const& obj)const;
		/**@brief 输出该对象的字符串描述*/
		virtual ptr<String> ToString()const;
		/**@brief 析构函数*/
		virtual ~Object() { if (UseCount != -1)UseCount.pCount->referenceCount &= MinValues::template Of<index_t>(); }
		/**@brief 获取该对象的类型*/
		virtual ptr<Type> GetType()const;
		/**@brief 交换两个变量的值，使用operator=*/
		template<class T>static inline typename UseIf<!IsBaseOf<PObject,T>::V>::T Swap(T& t1, T& t2)
		{
#ifdef SUPPORT_RIGHT_VALUE_REFERENCE
			T t = (T&&)t1; t1 = (T&&)t2; t2 = (T&&)t;
#else
			T t = t1; t1 = t2; t2 = t;
#endif
		}
		template<class T>static inline typename UseIf<IsBaseOf<PObject, T>::V>::T Swap(T& t1, T& t2);
		/**@brief 判断两个代理对象是否引用了同一个对象*/
		static bool ReferenceEqual(PObject t1, PObject t2);
		/**
		@brif 添加类型信息*/
		static void AddTypeInfo();
		/**
		@brief 判断两个代理对象是否相等*/
		static bool Equals(PObject t1, PObject t2);
	protected:
		static void ChangePtr(ptr<Object>&r, Object*p);
	private:
		friend struct ptr<Object>;
	};
	typedef ptr<Object > object;

	/**@brief 引用类型基类*/
	template<>struct ptr<Object>
	{
		/**
		@brief 用以推断被代理类型*/
		typedef Object IObj;
		/**
		@brief 用以推断代理类型*/
		typedef ptr<Object> PObj;
		/**
		@brief 默认构造函数*/
		inline ptr() :pObject(null) {}
		/**
		@brief 从空指针构造*/
		inline ptr(null_t) : pObject(null) {}
		/**
		@brief 析构函数*/
		inline ~ptr() { if (--UseCount == 0)delete pObject; }
		/**
		@brief 复制构造函数*/
		inline ptr(ptr const&t) :UseCount(t.UseCount), pObject((Object*)t.pObject) { if (UseCount <= 0)pObject = null; if (pObject)++(UseCount); }
		/**
		@brief 从除了PObject外的任意其它类型对象构造
		@param [模板]参数T不需要指定
		@note 构造规则：
		@note 1.如果对象是PObject的派生类，则直接引用增加；
		@note 2.如果对象可以隐式转换到Object*，那么将直接将Object*指向的对象进行引用；
		@note 3.如果对象是其它类型将进行MObject封箱操作*/
		template<typename TT>inline ptr(TT t) :pObject(null) { Ctor<TT>(t); }
		/*operator&重载*/
		Object& operator*()const { if (UseCount<0)++UseCount; return *Check(); }
		/**
		@brief 赋值*/
		inline ptr & operator=(ptr const&r) {
			if (r.pObject == pObject)return*this;
			Object* p;
			if (!r.UseCount.pCount)p = null;
			else {
				if (r.UseCount.pCount->GetEnableThreadSafe()) {
					r.UseCount.pCount->Lock();
					if (*r.UseCount.pCount == 0)p = null;
					else { ++*r.UseCount.pCount; p = r.pObject; }
					r.UseCount.pCount->UnLock();
				}
				else {
					if (*r.UseCount.pCount == 0)p = null;
					else { ++*r.UseCount.pCount; p = r.pObject; }
				}
			}
			if (UseCount>0){
				index_t cnt = --UseCount;
				if (cnt == 0)
					delete pObject;
				else
					UseCount.ChangeRef(null);
			}
			if (p) {
				UseCount = p->UseCount;
			}
			pObject = p;
			return *this; }
		/**
		@brief 置null*/
		inline ptr & operator=(null_t) {
			if (UseCount>0) {
				index_t cnt = --UseCount;
				if (cnt == 0)
					delete pObject;
				else
					UseCount.ChangeRef(null);
			}
			pObject = null;
			return *this;
		}
		/**
		@brief 获取对象指针，并在对象指针为空时抛出异常*/
		inline Object* Check()const { if (UseCount <= 0||!pObject)Throw<PPointerIsNullException >(); return pObject; }
		/**
		@brief 获取对象指针，但不进行检查*/
		inline Object* GetPtr()const { if (UseCount <= 0)return pObject = null; return pObject; }
		/**
		@brief 重载operator->*/
		inline Object* operator->()const { return Check(); }
		/**@brief 引用计数*/
		PRefCount UseCount;
		friend bool operator==(PObject&t1, PObject&t2) { if (t1.pObject == t2.pObject)return true; if (t1.pObject || t2.pObject)return false; return t1.pObject->Equals(t2); }
		friend bool operator!=(PObject&t1, PObject&t2) { if (t1.pObject == t2.pObject)return false; if (t1.pObject || t2.pObject)return true; return !t1.pObject->Equals(t2); }
		friend bool operator==(null_t, PObject&p2) { return null == p2.pObject; }
		friend bool operator!=(null_t, PObject&p2) { return null != p2.pObject; }
		bool operator==( null_t)const { return pObject == null; }
		bool operator!=(null_t)const { return pObject != null; }
	protected:
		/**
		@brief 将该引用设置为另一个指针，但必须小心保证这个指针是可用的*/
		void SetTo(Object const*p)	{
			if (p == pObject)return;
			if (UseCount>0){
				index_t cnt = --UseCount;
				if (cnt == 0)
					delete pObject;
				else 
					UseCount.ChangeRef(null);
			}
			if (p) {
				if (p->UseCount == -1 && UseCount.GetWeakRefCount() == 1){//对象从未被引用而且引用计数可重用
					++UseCount;
					p->UseCount = UseCount;
				}
				else {
					++(p->UseCount);
					UseCount = p->UseCount;
				}
			}
			pObject = (Object*)p;
		}
	private:
		//被代理对象指针
		mutable Object* pObject;
		/**
		@brief 从代理类对象构造方法*/
		void RefCtor(PObject const&r){
			if (!r.UseCount.pCount)pObject = NULL;
			else {
				if (r.UseCount.pCount->GetEnableThreadSafe()) {
					r.UseCount.pCount->Lock();
					if (*r.UseCount.pCount == 0)pObject = NULL;
					else { ++*r.UseCount.pCount; pObject = r.pObject; }
					r.UseCount.pCount->UnLock();
				}
				else {
					if (*r.UseCount.pCount == 0)pObject = NULL;
					else { ++*r.UseCount.pCount; pObject = r.pObject; }
				}
			}
			if (pObject) {
				UseCount = pObject->UseCount;
			}
		}
		/**
		@brief 构造方法
		@note 当对象可隐式转换到Object*或者是PObject的派生类时，进行转换代理，否则进行封箱*/
		template<class T>inline typename UseIf<!IsGCHandle<T>::V&&IsBaseOf<ptr<Object>, T>::V>::T Ctor(T const&r) { RefCtor((ptr<Object> const&)r); }
		template<class T>inline typename UseIf<!IsGCHandle<T>::V&&IsConvertible<T, Object const*>::V>::T Ctor(T const&t) { SetTo((Object*)t); }
		template<class T>inline typename UseIf<!IsGCHandle<T>::V&&!IsBaseOf<ptr<Object>, T>::V&&!IsConvertible<T, Object const*>::V>::T Ctor(typename AddConst<typename AddLValueReference<T>::T>::T t) { Ctor2 <T>(t); }
		template<class T>void Ctor2(typename AddConst<typename AddLValueReference<T>::T>::T t);
#ifdef _CLR
		template<class T>inline typename UseIf<IsGCHandle<T>::V&&!IsReference<T>::V>::T Ctor(T t) { Ctor3 <T>(t); }
		template<class T>inline typename UseIf<IsGCHandle<T>::V&&IsReference<T>::V>::T Ctor(T t) { Ctor4 <T>(t); }
		template<class T>void Ctor3(T t);
		template<class T>void Ctor4(T t);
#endif
		template<class T>T CastTo1()const;
		template<class T>T CastTo2()const;
		template<class T>friend struct weak;
		friend struct Object;
		/**
		@brief 转换到指定的代理，使用动态类型信息转换，转换失败时返回空引用，不抛出异常*/
		template<class T>friend typename UseIf<IsBaseOf<PObject, T>::V&&IsSame<T, typename RemoveAllExtents<T>::T>::V, T>::T cast(object const&obj) { return obj.CastTo1 <T>(); }
		/**
		@brief 转换到指定的类型，使用动态类型信息转换，转换失败时抛出异常*/
		template<class T>friend typename UseIf<!IsBaseOf<PObject, T>::V || !IsSame<T, typename RemoveAllExtents<T>::T>::V, T>::T cast(object const&obj) { return obj.CastTo2 <T>(); }
	};



}
